#ifndef __LINUX_RT_TCPCI_CORE_H
#define __LINUX_RT_TCPCI_CORE_H

#include "common.h"

/*---------------------------------------------------------------------------*/

#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK
#define CONFIG_TYPEC_NOTIFY_ATTACHWAIT
#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK */

#ifdef CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SRC
#undef CONFIG_TYPEC_NOTIFY_ATTACHWAIT
#define CONFIG_TYPEC_NOTIFY_ATTACHWAIT
#endif	/* CONFIG_TYPEC_NOTIFY_ATTACHWAIT_SNK */


#ifdef CONFIG_TCPC_FORCE_DISCHARGE_EXT
#define CONFIG_TCPC_EXT_DISCHARGE
#endif	/* CONFIG_TCPC_FORCE_DISCHARGE_EXT */

#ifdef CONFIG_TCPC_AUTO_DISCHARGE_EXT
#undef CONFIG_TCPC_EXT_DISCHARGE
#define CONFIG_TCPC_EXT_DISCHARGE
#endif	/* CONFIG_TCPC_AUTO_DISCHARGE_EXT */

/*---------------------------------------------------------------------------*/

/* TCPC Power Register Define */
#define TCPC_REG_POWER_STATUS_EXT_VSAFE0V	(1<<15)	/* extend */
#define TCPC_REG_POWER_STATUS_VBUS_PRES		(1<<2)

/* TCPC Alert Register Define */
#define TCPC_REG_ALERT_EXT_RA_DETACH		(1<<(16+5))
#define TCPC_REG_ALERT_EXT_WATCHDOG		(1<<(16+2))
#define TCPC_REG_ALERT_EXT_VBUS_80		(1<<(16+1))
#define TCPC_REG_ALERT_EXT_WAKEUP		(1<<(16+0))

#define TCPC_REG_ALERT_VBUS_DISCNCT (1<<11)
#define TCPC_REG_ALERT_RX_BUF_OVF   (1<<10)
#define TCPC_REG_ALERT_FAULT        (1<<9)
#define TCPC_REG_ALERT_V_ALARM_LO   (1<<8)
#define TCPC_REG_ALERT_V_ALARM_HI   (1<<7)
#define TCPC_REG_ALERT_TX_SUCCESS   (1<<6)
#define TCPC_REG_ALERT_TX_DISCARDED (1<<5)
#define TCPC_REG_ALERT_TX_FAILED    (1<<4)
#define TCPC_REG_ALERT_RX_HARD_RST  (1<<3)
#define TCPC_REG_ALERT_RX_STATUS    (1<<2)
#define TCPC_REG_ALERT_POWER_STATUS (1<<1)
#define TCPC_REG_ALERT_CC_STATUS    (1<<0)

#define TCPC_REG_ALERT_RX_MASK	\
	(TCPC_REG_ALERT_RX_STATUS | TCPC_REG_ALERT_RX_BUF_OVF)

#define TCPC_REG_ALERT_RX_ALL_MASK	\
	(TCPC_REG_ALERT_RX_MASK | TCPC_REG_ALERT_RX_HARD_RST)

#define TCPC_REG_ALERT_HRESET_SUCCESS	\
	(TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED)

#define TCPC_REG_ALERT_TX_MASK (TCPC_REG_ALERT_TX_SUCCESS | \
	TCPC_REG_ALERT_TX_FAILED | TCPC_REG_ALERT_TX_DISCARDED)

#define TCPC_REG_ALERT_TXRX_MASK	\
	(TCPC_REG_ALERT_TX_MASK | TCPC_REG_ALERT_RX_MASK)

#define TCPC_LOW_POWER_MODE_RETRY	5

/*
 * Confirm DUT is connected to legacy cable or not
 *	after suupect_counter > this threshold (0 = always check)
 */

#define TCPC_LEGACY_CABLE_SUSPECT_THD	1

/*
 * Try another s/w workaround after retry_counter more than this value
 * Try which soltuion first is determined by tcpc_flags
 */

#define TCPC_LEGACY_CABLE_RETRY_SOLUTION	2
 
 
#if 0
enum tcpc_cc_voltage_status {
	TYPEC_CC_VOLT_OPEN = 0,
	TYPEC_CC_VOLT_RA = 1,
	TYPEC_CC_VOLT_RD = 2,

	TYPEC_CC_VOLT_SNK_DFT = 5,
	TYPEC_CC_VOLT_SNK_1_5 = 6,
	TYPEC_CC_VOLT_SNK_3_0 = 7,

	TYPEC_CC_DRP_TOGGLING = 15,
};
#endif

 /* TCPC Behavior Flags */
#define TCPC_FLAGS_RETRY_CRC_DISCARD        (1<<0)
#define TCPC_FLAGS_CHECK_RA_DETACH          (1<<4)
#define TCPC_FLAGS_PD_REV30                 (1<<2)
#define TCPC_FLAGS_WATER_DETECTION          (1<<4)
#define TCPC_FLAGS_CABLE_TYPE_DETECTION     (1<<5)
#define TCPC_FLAGS_VCONN_SAFE5V_ONLY        (1<<6)
#define TCPC_FLAGS_ALERT_V10                (1<<7)
#define TCPC_FLAGS_FOREIGN_OBJECT_DETECTION (1<<8)
#define TCPC_FLAGS_TYPEC_OTP                (1<<9)
#define TCPC_FLAGS_FLOATING_GROUND          (1<<10)
#define TCPC_FLAGS_WD_DUAL_PORT             (1<<11)
#define TCPC_FLAGS_VBUS_SHORT_CC            (1<<12)

#define TCPC_VBUS_SOURCE_0V         (0)
#define TCPC_VBUS_SOURCE_5V         (5000)
#define TCPC_VBUS_SINK_0V           (0)
#define TCPC_VBUS_SINK_5V           (5000)

#define TYPEC_CC_PULL_GET_RES(pull)     ((pull) & 0x07)
#define TYPEC_CC_PULL_GET_RP_LVL(pull)  (((pull) & 0x18) >> 3)
#define TYPEC_CC_PULL(rp_lvl, res)      (((rp_lvl) & 0x03) << 3 | ((res) & 0x07))

enum tcpc_rp_lvl {
    TYPEC_RP_DFT,
    TYPEC_RP_1_5,
    TYPEC_RP_3_0,
    TYPEC_RP_RSV,
};

enum tcpc_cc_pull {
    TYPEC_CC_RA = 0,
    TYPEC_CC_RP = 1,
    TYPEC_CC_RD = 2,
    TYPEC_CC_OPEN = 3,
    TYPEC_CC_DRP = 4,       /* from Rd */

    TYPEC_CC_RP_DFT = TYPEC_CC_PULL(TYPEC_RP_DFT, TYPEC_CC_RP),
    TYPEC_CC_RP_1_5 = TYPEC_CC_PULL(TYPEC_RP_1_5, TYPEC_CC_RP),
    TYPEC_CC_RP_3_0 = TYPEC_CC_PULL(TYPEC_RP_3_0, TYPEC_CC_RP),

    TYPEC_CC_DRP_DFT = TYPEC_CC_PULL(TYPEC_RP_DFT, TYPEC_CC_DRP),
    TYPEC_CC_DRP_1_5 = TYPEC_CC_PULL(TYPEC_RP_1_5, TYPEC_CC_DRP),
    TYPEC_CC_DRP_3_0 = TYPEC_CC_PULL(TYPEC_RP_3_0, TYPEC_CC_DRP),
};

enum tcpm_rx_cap_type {
    TCPC_RX_CAP_SOP = 1 << 0,
    TCPC_RX_CAP_SOP_PRIME = 1 << 1,
    TCPC_RX_CAP_SOP_PRIME_PRIME = 1 << 2,
    TCPC_RX_CAP_SOP_DEBUG_PRIME = 1 << 3,
    TCPC_RX_CAP_SOP_DEBUG_PRIME_PRIME = 1 << 4,
    TCPC_RX_CAP_HARD_RESET = 1 << 5,
    TCPC_RX_CAP_CABLE_RESET = 1 << 6,
};

static inline uint8_t pd_get_rev(struct pd_port *pd_port, uint8_t sop_type)
{
	uint8_t pd_rev = PD_REV20;
#if CONFIG_USB_PD_REV30_SYNC_SPEC_REV
	struct pe_data *pe_data = &pd_port->pe_data;
	struct sgm41620_tcpc *tcpc = p_tcpc_dev;

	if (sop_type == TCPC_TX_SOP) {
		pd_rev = pd_port->pd_revision[0];
	} else {
		if (pe_data->explicit_contract || pe_data->cable_rev_discovered)
			pd_rev = pd_port->pd_revision[1];
		else if (tcpc->tcpc_flags & TCPC_FLAGS_PD_REV30)
			pd_rev = PD_REV30;
	}
#endif	/* CONFIG_USB_PD_REV30_SYNC_SPEC_REV */

	return pd_rev;
}

static inline bool pd_check_rev30(struct pd_port *pd_port)
{
	//return true;
	return pd_get_rev(pd_port, TCPC_TX_SOP) >= PD_REV30;
}

void tcpc_device_register(void);
void tcpc_schedule_init_work(void);

#endif /* #ifndef __LINUX_RT_TCPCI_CORE_H */

